package fms.controller;

import fms.acarsMsgProcessUtil.DownLinkDatagramHeader;
import fms.acarsMsgProcessUtil.RawDatagram;
import fms.core.*;
import fms.dao.CptSendService;
import fms.model.CptSend;
import fms.msgupcenter.protocols.AcarsProtocol;
import fms.msgupcenter.protocols.uplinkmsg.UplinkMsgProtocol;
import fms.util.*;
import fms.webservice.*;
import fms.xml.WindRequestXML;
import fms.xml.WindResponseXML;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/*  测试报文
2014-07-21 03:23:47
QU SHAQPHO
.BJSXCXA 210310
FML
FI 9C8554/AN B-9920
DT BJS PVG 260310 F09A
-  REQPWI/CQ351/WQ351:ZGSZ.IDUMA.KEVAR.SHL/DQ351/WRZYCC.ZYTXA130

2014-07-21 03:23:47
QU SHAQPHO
.BJSXCXA 210310
FML
FI HO1161/AN B-6619
DT BJS PVG 260310 F09A
-  REQPWI/CQ100/WQ100:ZYTL.ALDAP.ODULO.GORPI/DQ100/WRZYCC.ZYTXA130

2014-07-21 03:23:47
QU HAKDPHU
.BJSXCXA 210310
FML
FI HU0000/AN B-0000
DT BJS PVG 260310 F09A
-  REQPWI/CQ100/WQ100:ZYTL.ALDAP.ODULO.GORPI/DQ100/WRZYCC.ZYTXA130


2014-07-21 03:23:47
QU SHAQPHO
.BJSXCXA 210310
FML
FI HO1161/AN B-6619
DT BJS PVG 260310 F09A
-  REQPWI/CQ180/WQ180:IBEGI.ALDAP.ODULO.GORPI/DQ180/WRZYCC.ZYTXA130


QU HAKDPHU
FML
FI HU482/AN B-2739
DT BJS PVG 260310 F09A
-  REQPWI/CQ100/WQ100:HYLND.TOC.TAYTA.FIR.OLMIN.PILUN.RESBU.ZBAA/DQ100/WRZYCC.ZYTXA130


多个高度层请求样例：
QU SHAQPHO
.BJSXCXA 091529
FML
FI HO1074/AN B-6381
DT BJS TAO 091529 F04A
- REQPWI/CQ217/WQ370.330.240:BINOR.SOSMA/DQ217/WRZSPD.ZSNJ0E9E


      PWI/WD240,ODULO,290070,240M16.GORPI,290076,240M17.
*/
/**
 * 风温请求与回复模块处理流程：
 * 1、接收过滤报文（我们这个系统不需要考虑发送失败的情况，不用处理回执报）；
 * 2、从原始报文中解析风温请求，生成请求对象（高度层去重复）；
 * 3、调用“webservice查询飞行计划风温数据”或“Grib2风温数据计算”；
 * 4、组装Acars风温回复报文自由文（若超长，采用按高度层进行分组回复机制）、Msgupcenter协议串；
 * 5、依次发送分组回复的Msgupcenter协议串，并保存Acars风温回复报文自由文，用于skyfms web监控系统使用；
 * */

public class WindController implements IReceiver{
//    public class WindController implements Observer {


    private Logger logger = Logger.getLogger(WindController.class);
    //线程池,设置固定10个线程
    ExecutorService pool = Executors.newFixedThreadPool(10);

    // 用于筛选过滤出“REQ请求报文”
    private IFilter filter;
    // 解析风温请求报文的类
    private DownRequestWind downRequestWind;
    // 用于访问数据库，获取风温请求数据的webservice接口
    private WindService windService;
    // 用于组装应答报文的的接口（按情况实例化成风温组装类、位置报）
    private WindMsgBuilder windMsgBuilder;
    // 利用msgupCenter中的协议工具生成acars620格式的上行XML报文
    private WindXmlBuilder windXmlBuilder;
    // 在spring中按需配置activeMQsender或msmq
    private ISender sender;
    private String upMessageCache = "";

    public final static String Grib2PointTableCPT = "CPTINFO";
    public final static String Grib2PointTableNAIP = "NAIP";

    public IFilter getFilter() {
        return filter;
    }

    public void setFilter(IFilter filter) {
        this.filter = filter;
    }

    public DownRequestWind getDownRequestWind() {
        return downRequestWind;
    }

    public void setDownRequestWind(DownRequestWind downRequestWind) {
        this.downRequestWind = downRequestWind;
    }

    public Logger getLogger() {
        return logger;
    }

    public void setLogger(Logger logger) {
        this.logger = logger;
    }

    public WindService getWindService() {
        return windService;
    }

    public void setWindService(WindService windService) {
        this.windService = windService;
    }

    public ISender getSender() {
        return sender;
    }

    public String getUpMessageCache() {
        return upMessageCache;
    }

    public void setUpMessageCache(String upMessageCache) {
        this.upMessageCache = upMessageCache;
    }

    public void setSender(ISender sender) {
        this.sender = sender;
    }


    public WindMsgBuilder getWindMsgBuilder() {
        return windMsgBuilder;
    }

    public void setWindMsgBuilder(WindMsgBuilder windMsgBuilder) {
        this.windMsgBuilder = windMsgBuilder;
    }

    public WindXmlBuilder getWindXmlBuilder() {
        return windXmlBuilder;
    }

    public void setWindXmlBuilder(WindXmlBuilder windXmlBuilder) {
        this.windXmlBuilder = windXmlBuilder;
    }

    public WindController() {
    }

//    public void update(Observable observable, Object arg) {
//        String aContent = (String) arg;
//
//        if (filter.isFilter(aContent) == false) {
//            return;
//        } else {
//            Logger windRequestLogger = Logger.getLogger("windRequestContent");
//            windRequestLogger.info("风温请求内容：\r\n"+aContent);
//            DealWind dealWindRequsest = new DealWind(aContent,downRequestWind, windService, windMsgBuilder, windXmlBuilder, sender);
//            pool.execute(dealWindRequsest);
//        }
//    }

    public void receiveMsg(Object arg) {
        String aContent = (String) arg;

        if (filter.isFilter(aContent) == false) {
            return;
        } else {
            Logger windRequestLogger = Logger.getLogger("windRequestContent");
            DealWind dealWindRequsest = new DealWind(aContent,downRequestWind, windService, windMsgBuilder, windXmlBuilder, sender);
            pool.execute(dealWindRequsest);
        }
    }

    /**
     * 保存grib2数据线程
     */
    private static class DealWind implements Runnable {
        private Logger logger = Logger.getLogger(DealWind.class);

        private String conent;

        // 加载飞行计划中不包含风温度信息的航空公司列表
        private String planNoHasWindTempAirlines = "";

        // 如果，该机尾号没有指定配置上行SMI，就按下行请求的SMI回复
        private String upResponseSMI = "";
        // 上行回复配置列表（机尾号,回复SMI）
        private Map<String, String> mapAircreftRespSMI = new HashMap<String, String>();
        // 航空公司二字码与航路点经纬度来源对照表
        private Map<String, String> maprequesTypeCodes = new HashMap();

        // 解析风温请求报文的类
        private DownRequestWind downRequestWind;
        // 用于访问数据库，获取风温请求数据的webservice接口
        private WindService windService;
        // 用于组装应答报文的的接口（按情况实例化成风温组装类、位置报）
        private WindMsgBuilder windMsgBuilder;
        // 利用msgupCenter中的协议工具生成acars620格式的上行XML报文
        private WindXmlBuilder windXmlBuilder;
        // 在spring中按需配置activeMQsender或msmq
        private ISender sender;


        private String uplinkformat;
        private String uplinkreceiver;
        private String uplinksender;
        private String snavailable;

        public String getConent() {
            return conent;
        }

        public void setConent(String conent) {
            this.conent = conent;
        }

        public String getPlanNoHasWindTempAirlines() {
            return planNoHasWindTempAirlines;
        }

        public void setPlanNoHasWindTempAirlines(String planNoHasWindTempAirlines) {
            this.planNoHasWindTempAirlines = planNoHasWindTempAirlines;
        }

        public DownRequestWind getDownRequestWind() {
            return downRequestWind;
        }

        public void setDownRequestWind(DownRequestWind downRequestWind) {
            this.downRequestWind = downRequestWind;
        }

        public WindService getWindService() {
            return windService;
        }

        public void setWindService(WindService windService) {
            this.windService = windService;
        }

        public WindMsgBuilder getWindMsgBuilder() {
            return windMsgBuilder;
        }

        public void setWindMsgBuilder(WindMsgBuilder windMsgBuilder) {
            this.windMsgBuilder = windMsgBuilder;
        }

        public WindXmlBuilder getWindXmlBuilder() {
            return windXmlBuilder;
        }

        public void setWindXmlBuilder(WindXmlBuilder windXmlBuilder) {
            this.windXmlBuilder = windXmlBuilder;
        }

        public ISender getSender() {
            return sender;
        }

        public void setSender(ISender sender) {
            this.sender = sender;
        }

        public DealWind(String conent, DownRequestWind downRequestWind, WindService windService, WindMsgBuilder windMsgBuilder, WindXmlBuilder windXmlBuilder, ISender sender) {
            this.conent = conent;
            this.downRequestWind = downRequestWind;
            this.windService = windService;
            this.windMsgBuilder = windMsgBuilder;
            this.windXmlBuilder = windXmlBuilder;
            this.sender = sender;

            File fBaseParam = new File(ConfUtil.props.getProperty("baseParamFilePath"));
            uplinkformat=ConfUtil.props.getProperty("uplinkformat");
            uplinksender=ConfUtil.props.getProperty("uplinksender");
            uplinkreceiver=ConfUtil.props.getProperty("uplinkreceiver");
            snavailable=ConfUtil.props.getProperty("snavailable");

            final SAXReader readerBaseParam = new SAXReader();
            try {
                final Document paraseRulenDoc = readerBaseParam.read(fBaseParam);
//                logger.debug("[开始] 飞行计划中没有风温数据的航空公司列表加载！");
                Element uniqueObject = (Element) paraseRulenDoc.selectSingleNode("/baseParamter/coreService/windController/planNoHasWindTemp");
                planNoHasWindTempAirlines = uniqueObject.getText();
//                logger.debug("[结束] 飞行计划中没有风温数据的航空公司列表加载！");

//                logger.debug("[开始] 机尾号与上行回复SMI对照表加载！");
                List upResponseSmiList = paraseRulenDoc.selectNodes("/baseParamter/coreService/windController/UpResponseSMI");
                Iterator it = upResponseSmiList.iterator();
                while (it.hasNext()) {
                    Element aircraftSmi = (Element) it.next();
                    mapAircreftRespSMI.put(aircraftSmi.getTextTrim().split(",")[0], aircraftSmi.getTextTrim().split(",")[1]);
                }
//                logger.debug("[结束] 机尾号与上行回复SMI对照表加载！");

//                logger.debug("[开始] 航空公司二字码与航路点经纬度数据源对照表加载！");
                List requestTypelist = paraseRulenDoc.selectNodes("/baseParamter/coreService/windController/requestDaTaSource");
                it = requestTypelist.iterator();
                while (it.hasNext()) {
                    Element requestCode = (Element) it.next();
                    maprequesTypeCodes.put(requestCode.getTextTrim(), requestCode.attributeValue("requestType"));
                }
//                logger.debug("[完成] 航空公司二字码与航路点经纬度数据源对照表加载！");

            } catch (Exception e) {
                logger.error(e.toString());
            }
        }

        public void dealWind(String aContent, DownRequestWind downRequestWind, WindMsgBuilder windMsgBuilder,
                             WindXmlBuilder windXmlBuilder, ISender sender, WindService windService) {

//            String uplinkack = "UPLINKACK";
//            String uplink = "UPLINK";
//
//            //判断报文类型是否为回执报，若为回执报，则将回执报中参数与上行报文缓存进行比较，
//            //检查是否匹配，匹配则将上行报文缓存置空，不匹配则再发送一次上行报文
//            if (aContent.contains(uplinkack)) {
//                if(upMessageCache.equals("")) {
//                    //如果收到的是回执报，并且缓存上行报文为空，原因是上一次的回执报与缓存上行报
//                    //信息不匹配而进行的重发
//                } else {
//                    //如果收到的是回执报，并且缓存上行报文不为空，则进行回执报与缓存上行报信息匹配
//                    //compare(aContent,upMessageCache);
//                    //匹配成功则将缓存上行报置为空，匹配不成功则重新发送一次缓存上行报
//                }
//                sender.send(upMessageCache);
//                upMessageCache = "";
//            //////// 3、风温请求报处理
//            } else if(aContent.contains(uplink)) {

            logger.debug("报文格式符合要求，进行解析处理!");
            try {
                DownLinkDatagramHeader msgHeader = null;
                /**
                 * 下面几行代码实现：默认上行回复与下行请求SMI保持一致，如果配置了该机尾号的上行回复SMI就使用
                 * */
                try {
                    msgHeader = DownLinkDatagramHeader.Parse(RawDatagram.GetHeader(aContent));
                    upResponseSMI = msgHeader.getSmi();
                    if( !ObjectUtil.isBlank(mapAircreftRespSMI.get(msgHeader.getAn())) ) {
                        upResponseSMI = mapAircreftRespSMI.get(msgHeader.getAn());
                    }
                } catch (Exception e) {
                    // 报头解析异常，该报文不是正规的acars报文，可略过
                    throw new Exception("dealWind() 报文头解析出错！" + e.getMessage() + "\r\n出错报文为：\r\n" + aContent);
                }

                Request request = downRequestWind.parse(aContent);
                if (null == request) {
                    throw new Exception("风温请求解析失败！");
                }
                WindRequestXML windRequestXML = XmlUtil.unMarshallWindRequest(request.getRequestXML());


                logger.info("服务进行风温请求，本次请求信息为：" + "\r\n" + request.getRequestXML());

                /**
                 * 根据配置文件决定如何获取风温数据：Grib2还是飞行计划
                 */
                if ((windRequestXML.getFlightID() != null
                        && "GRID2".equals(maprequesTypeCodes.get(windRequestXML.getFlightID().substring(0, 2) + "." + Grib2PointTableCPT)))
                        || (windRequestXML.getFlightID() != null
                        && "GRID2".equals(maprequesTypeCodes.get(windRequestXML.getFlightID().substring(0, 2) + "." + Grib2PointTableNAIP)))) {
                    Grib2Controller grib2Controller = null;

                    //请求grid2数据的风温返回
                    WindResponseXML windResponseXML = null;
                    if ("GRID2".equals(maprequesTypeCodes.get(windRequestXML.getFlightID().substring(0, 2) + "." + Grib2PointTableNAIP))) {
                        grib2Controller = new Grib2Controller(Grib2PointTableNAIP);
                    } else {
                        grib2Controller = new Grib2Controller(Grib2PointTableCPT);
                    }

                    windResponseXML = grib2Controller.gerGrid2Response(request);
                    buildSendContent(windRequestXML, windResponseXML, aContent, SysConstants.DATA_FILL_RULE_LEFT);
                } else {
                    //请求飞行计划数据的风温返回
                    WindResponseXML windResponseXML = windService.getWind(request);
                    buildSendContent(windRequestXML, windResponseXML, aContent, SysConstants.DATA_FILL_RULE_RIGHT);
                }
            } catch (Exception e) {
                   e.printStackTrace();
                logger.error("风温请求失败：" + e.getMessage());
                return;
            }
        }

        /**
         *
         *      本函数主要处理了“风温回复报文一旦超长，采用逐高度层分组上发机制”；
         * 分组上发算法说明：
         *      1、假设一次风温请求中，包含了noRepeatN个高度层的请求（不含重复高度层）；
         *      2、利用Grib2风温计算结果（这个结果集中包含了所有高度层、航路点的风温数据，若请求高度层重复，结果集中包含重复数据）组成包含“第一个”至“第noRepeatN个”高度层的风温回复报文acarsFreeTextMSG；
         *      3、如果，acarsFreeTextMSG超过配置长度，那么，就利用Grib2风温计算结果组成包含“第一个”至“第noRepeatN - 1个”高度层的风温回复报文acarsFreeTextMSG2；
         *      4、如果，acarsFreeTextMSG2超过配置长度，那么，就利用Grib2风温计算结果组成包含“第一个”至“第noRepeatN - 2个”高度层的风温回复报文acarsFreeTextMSGn；
         *      5、如果，acarsFreeTextMSGn超过配置长度，那么，就利用Grib2风温计算结果组成包含“第一个”至“第n个”高度层的风温回复报文acarsFreeTextMSGm；
         *      6、如果，acarsFreeTextMSGm不超过配置长度，就由acarsFreeTextMSGm生成发送给MSGUPCENTER的协议串，保存至freeAllOfUpMsgList中以备发送，并将acarsFreeTextMSGm保存到freeTextOfUpMsgList以备入库监控；
         *      7、按照2-6描述的算法，对“第n个”至“第noRepeatN个”高度层，生成相应的风温回复报文；
         */
        public void  buildSendContent(  WindRequestXML windRequestXML, WindResponseXML windResponseXML, String aContent, String dirAppendZeroRule){
            logger.debug("风温数据请求完成，响应信息为：" + "\r\n" + XmlUtil.marshallWindResponse(windResponseXML) + "\r\n" + "开始构造上传报文!");
            String freeTextOfUpMsg = "";
            String freeAllOfUpMsg ="";
            String flightLevels="";
            if (null != windResponseXML && ErrorLevel.Success.equals(windResponseXML.getResultcode())) {
                try {
                    Logger windResponseLogger = Logger.getLogger("windResponseContent");

                    // acars一次可发送的报文最大长度
                    String maxSendLength = ConfUtil.props.getProperty("maxSendLength");
                    // acars报头字节数
                    final int acarsTitleSize = 200;

                    String[] reqAlts = windRequestXML.getAlt().split("\\.");

                    // 标记变量：当前风温回复报包括的高度层数据，起始位置
                    int startMarkAlt = 0;
                    // 标记变量：当前风温回复报包括的高度层数据，终止位置
                    int endMarkAlt = 0;
                    // 回复报文中，含有的高度层数量
                    int allAlt = 0;
                    if( (reqAlts != null) && (reqAlts.length > 0) ){
                        allAlt = reqAlts.length;
                    }
                    endMarkAlt = allAlt;
                    // 一次风温请求回复报文中，发送到 MSGUPCENTER 的内容列表（因为，超长后分组上发）
                    List freeAllOfUpMsgList = new ArrayList();
                    // 分组上发时，每份报文中 自由文 列表
                    List freeTextOfUpMsgList = new ArrayList();
                    List flightLevelList=new ArrayList();
                    if(maxSendLength != null) {
                        while (startMarkAlt < allAlt) {
                            freeTextOfUpMsg = windMsgBuilder.build(windRequestXML, windResponseXML, planNoHasWindTempAirlines,
                                    dirAppendZeroRule, startMarkAlt, endMarkAlt);
                            if (ObjectUtil.isBlank(freeTextOfUpMsg)) {
                                logger.error("风温数据组报，fmlMsgBuilder.build 组装Acars报正文失败！");
                                return;
                            }
                            if( freeTextOfUpMsg.length() > Integer.valueOf(maxSendLength) - acarsTitleSize ){
                                // 本次风温请求只请求一个高度层数据，且回复长度超过acars传输限制
                                if(endMarkAlt == 1){
                                    windResponseLogger.info("当前风温回复报文的总长度是：" + freeTextOfUpMsg.length() + "超过定义的最大长度！");
                                    break;
                                    // 本次风温请求请求若干高度层数据，且仅回复第一个高度的风温数据时，回复报文长度超过acars传输限制
                                } else if( endMarkAlt - startMarkAlt == 1 ) {
                                    windResponseLogger.info("当前风温回复报文的总长度是：" + freeTextOfUpMsg.length() + "超过定义的最大长度！");
                                    break;
                                } else {
                                    endMarkAlt--;
                                }
                            }
                            else{
                                if(uplinkformat.equals("xml")){
                                    freeAllOfUpMsg = windXmlBuilder.build(aContent, freeTextOfUpMsg, upResponseSMI);
                                }
                                else{
                                    freeAllOfUpMsg = Msg620Builder.build(windRequestXML.getAircraftid(), freeTextOfUpMsg, upResponseSMI,uplinksender,uplinkreceiver,snavailable);
                                }
                                if (ObjectUtil.isBlank(freeAllOfUpMsg)) {
                                    logger.error("风温数据组报，windXmlBuilder.build组装MsgUpCenter报文失败！");
                                    return;
                                }
                                startMarkAlt = endMarkAlt;
                                endMarkAlt = allAlt;
                                freeAllOfUpMsgList.add(freeAllOfUpMsg);
                                freeTextOfUpMsgList.add(freeTextOfUpMsg);
                                //获取当前结果中高度层（组）给web界面使用
                                if(freeTextOfUpMsg.contains("WD")){
                                    String[] temp=freeTextOfUpMsg.split("WD");
                                    //只有一个高度层
                                    if(temp.length==2){
                                        flightLevels="FL"+temp[1].substring(0,3);
                                    }
                                    else{
                                        for(int fl=1;fl<temp.length;fl++){
                                            flightLevels=flightLevels+"FL"+temp[fl].substring(0, 3) +"/";
                                        }
                                        flightLevels=flightLevels.substring(0,flightLevels.length()-1);
                                    }
                                    flightLevelList.add(flightLevels);
                                }

                            }
                        }
                    } // if(maxSendLength != null) {

                    // 按高度层分组发送风温回复报文
                    for(int i = 0; i < freeAllOfUpMsgList.size(); i++){
                        List listdata = windResponseXML.getDatas();
                        // 有Grib2计算结果的才发送，没有风温数据的就不用发送(在saveSendContent保存数据时，进一步判断是否是由于没有飞行计划导致的无法计算出风温数据)
                        if( (listdata != null) && (listdata.size() > 0) ){
                            windResponseLogger.info("Acars自由文的总长度是：" + freeTextOfUpMsgList.get(i).toString().length());
                            String appUpMsgId ="";
                            String masNum="";
                            if(uplinkformat.equals("xml")){
                                windResponseLogger.info("MsgUpCenter格式的上行XML报文构造完成,上发内容是：\r\n" + freeAllOfUpMsgList.get(i));

                                UplinkMsgProtocol protocol = (UplinkMsgProtocol) AcarsProtocol.Deserialize(
                                        freeAllOfUpMsgList.get(i).toString(), UplinkMsgProtocol.class);
                                appUpMsgId = protocol.body.uplinkMessage.getHead().getAppUpMsgId();
                                String tmp=freeAllOfUpMsgList.get(i).toString();
                                tmp=tmp.replace("                <appUpMsgId>"+appUpMsgId+"</appUpMsgId>\n","");
                                freeAllOfUpMsgList.set(i,tmp);
                            }
                            else{
                                windResponseLogger.info("MsgUpCenter格式的上行620报文构造完成,上发内容是：\r\n" + freeAllOfUpMsgList.get(i));
                                int indexMA=freeAllOfUpMsgList.get(i).toString().indexOf("/MA");
                                masNum=freeAllOfUpMsgList.get(i).toString().substring(indexMA+4,indexMA+8);
                                int indexSN=freeAllOfUpMsgList.get(i).toString().indexOf("/SN");
                                if(indexSN!=-1){
                                    appUpMsgId=freeAllOfUpMsgList.get(i).toString().substring(indexSN + 3,indexSN+13);
                                }
                            }
                            sender.send(freeAllOfUpMsgList.get(i).toString());
                            saveSendContent(windRequestXML, freeTextOfUpMsgList.get(i).toString(), appUpMsgId,masNum,flightLevelList.get(i).toString(),"1");
                        }else{
                            logger.error("航班号："+windRequestXML.getFlightID() + "，机尾号：" + windRequestXML.getAircraftid() + "，风温请求没有计算出结果（初步断定原因为：无Grib2数据）！");
                            saveSendContent(windRequestXML,  "", "","","","4");
                        }
                    }
                } catch (Exception ex) {
                    logger.error("风温组报错误：", ex);
                    return;
                }
            } else {
                logger.error("风温请求失败，没有获取到数据，状态代码为：" + windResponseXML.getResultcode());
                return;
            }
        }

        /**
         * 保存上发的信息
         * @param windRequestXML
         * @param freeTextOfUpMsg
         */
        public  void saveSendContent( WindRequestXML windRequestXML,String freeTextOfUpMsg,String appUpMsgId,String masNum,String flightLevels,String sendStatus ){
            CptSendService cptSendService = ConfUtil.getSingletonApplicationContextDao().getBean("cptSendService", CptSendService.class);
            CptSend cptSend = new CptSend();
//                    List listwid=cptSendService.findCptSendwid(windRequestXML.getFlightID().substring(2,windRequestXML.getFlightID().length()), windRequestXML.getAircraftid());
//                    if (listwid!=null &&listwid.size()>0&&listwid.get(0)!=null){
//                        cptSend=(CptSend)listwid.get(0);
//                    }

            String curUTCTime = DateUtil.getCurUTCtime(SysConstants.FORMAT_DATETIME_FULL);
            String flyPlanValidTime = null;
            try {
                flyPlanValidTime = DateUtil.changeDay(curUTCTime, -2, SysConstants.FORMAT_DATETIME_FULL);
            }
            catch (ParseException e) {
                logger.error("DealWind-saveSendContent:获取24小时前的UTC时刻失败，无法将风温回复报文入库！");
                return;
            }

            // 查询相应航班飞行计划入库数据，更新当前回复报文的数据
            // 判定航班计划的规则是：航班号匹配、机位号匹配、两天内、按飞行计划日期降序排序的第一条数据
            List list = cptSendService.findCptSend(windRequestXML.getFlightID(), windRequestXML.getAircraftid(), flyPlanValidTime);
            if (list != null && list.size() > 0 && list.get(0) != null) {
                // 飞行计划一定先于某个风温回复数据产生，所以，查到的第一条记录一定是包含飞行计划信息的“飞行计划记录”or“风温回复记录”
                CptSend cptSend1 = (CptSend) list.get(0);
                cptSend.setArr(cptSend1.getArr());
                cptSend.setDep(cptSend1.getDep());
                cptSend.setRouteline(cptSend1.getRouteline());
                cptSend.setPlanDate(cptSend1.getPlanDate());
                cptSend.setPlanId(cptSend1.getPlanId());
                cptSend.setAirlines(cptSend1.getAirlines());
                cptSend.setSendStatus(sendStatus);
            }
            else{
                logger.error("航班号："+windRequestXML.getFlightID() + "，机尾号：" + windRequestXML.getAircraftid() + "，风温请求没有计算出结果（原因为：无飞行计划）！");
                // 没有飞行计划
                cptSend.setSendStatus("3");
            }
            cptSend.setFlightId(windRequestXML.getFlightID());
            cptSend.setAircraftId(windRequestXML.getAircraftid());
            cptSend.setSendType("1");
            cptSend.setSendContent(freeTextOfUpMsg);

            cptSend.setSendDate(DateUtil.getUTCTime());
            cptSend.setAppUpMsgId(appUpMsgId);
            cptSend.setMasNum(masNum);
            cptSend.setFlightLevels(flightLevels);
            cptSend.setCaptainStatus("0");
            // 新new的cptSend对象中ID一定是空的，这里就是save，不可能是update
            cptSendService.saveOrUpdate(cptSend);
        }
        @Override
        public void run() {
            dealWind(conent, downRequestWind, windMsgBuilder, windXmlBuilder, sender, windService);
        }


    }
}